home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
276-300
/
289
/
amigo
/
killable.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-14
|
13KB
|
377 lines
/* By Stoney Ballard */
/* Ported from Pascal to C by Todd R. Johnson */
#include "go.h"
#include "goplayutils.h"
extern intBoard bord, groupIDs;
extern boolBoard legal;
extern tryPlay( short, short, short );
extern sSpanGroup( short, short, sPointList * );
extern spanGroup( short, short, pointList *);
extern pause();
extern groupRec gList[maxGroup];
extern short gMap[maxGroup], adjInAtari, adj2Libs, playMark, treeLibLim,
utilPlayLevel, killFlag, depthLimit, dbStop, showTrees;
extern pointList plist2;
/*
returns true if the group (at x, y) is killable.
if so, returns the point to play at in killx, killy.
*/
short me, him, depth, i, j, tryCount, tl, topMark, tkMark, mark2;
char sChar;
sPointList lList, dList;
point tp;
short libList[maxSPoint+1];
short esc;
short mtNbrs(x, y)
short x, y;
{ /* mtNbrs */
short n = 0;
if ((x > 0) && (bord[x - 1][y] == 0))
n = n + 1;
if ((x < maxPoint) && (bord[x + 1][y] == 0))
n = n + 1;
if ((y > 0) && (bord[x][y - 1] == 0))
n = n + 1;
if ((y < maxPoint) && (bord[x][y + 1] == 0))
n = n + 1;
return n;
} /* mtNbrs */
short killTree(tx, ty, gx, gy, escape, tkMark)
short tx, ty, gx, gy, *escape, tkMark;
{ /* killTree */
short curMark, mark2, mark3, i, j, k, tl, dStart, result;
sPointList lList1, lList2;
short libList[maxSPoint+1];
point tp;
short esc = FALSE;
tryCount = tryCount + 1;
if (tryCount > tryLimit)
{
undoTo(tkMark);
/* for (i = 1; i <= depth - 1; i++)
{
sClearChar(sChar, rXor);
} */
depth = 1;
return FALSE;
}
/* write(sChar); */
depth = depth + 1;
curMark = playMark;
tryPlay(tx, ty, me); /* try my move */
pause();
if (gList[gMap[groupIDs[tx][ty]]].libC == 0) /* I'm dead */
{
result = FALSE;
goto one;
}
else if (killFlag) /* I killed something of his */
{
result = TRUE;
goto one;
}
else if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim) /* safe */
{
result = FALSE;
goto one;
}
else
{
sSpanGroup(gx, gy, &lList1); /* find his liberties */
if (gList[gMap[groupIDs[tx][ty]]].libC == 1) /* he can kill me */
{
if (lList1.indx < maxSPoint) /* add that option to his list */
{
lList1.indx = lList1.indx + 1;
spanGroup(tx, ty, &plist2); /* find my liberty */
lList1.p[lList1.indx].px = plist2.p[1].px;
lList1.p[lList1.indx].py = plist2.p[1].py;
}
else
{
result = FALSE;
goto one;
}
}
for (i = 1; i <= maxSPoint; i++) /* init liblist so diags can be marked */
libList[i] = -1;
if ((utilPlayLevel > 4) &&
(lList1.indx > 1) &&
(gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* try diags */
{
listDiags(gx, gy, &dList);
j = 0;
i = lList1.indx;
while ((j < dList.indx) &&
(i < maxSPoint))
{
j = j + 1;
i = i + 1;
libList[i] = 0; /* mark this as a diag */
lList1.p[i].px = dList.p[j].px;
lList1.p[i].py = dList.p[j].py;
}
lList1.indx = i;
}
if (lList1.indx > 1) /* sort by decreasing lib count */
{
for (i = 1; i <= lList1.indx; i++)
if (libList[i] != 0) /* diags are tried last */
{
mark2 = playMark;
tryPlay(lList1.p[i].px, lList1.p[i].py, him);
libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
if ((libList[i] > treeLibLim) ||
((libList[i] > (depthLimit - depth)) &&
(libList[i] > 2)))
{
*escape = TRUE;
result = FALSE;
goto one;
}
undoTo(mark2);
}
for (i = 1; i <= lList1.indx - 1; i++)
for (j = i + 1; j <= lList1.indx; j++)
if (libList[i] < libList[j])
{
tl = libList[i];
libList[i] = libList[j];
libList[j] = tl;
tp = lList1.p[i];
lList1.p[i] = lList1.p[j];
lList1.p[j] = tp;
}
}
for (i = 1; i <= lList1.indx + 1; i++) /* try his responses */
{
mark2 = playMark;
if (i <= lList1.indx) /* try his move */
{
tryPlay(lList1.p[i].px, lList1.p[i].py, him); /* play his response */
pause();
if (gList[gMap[groupIDs[lList1.p[i].px]
[lList1.p[i].py]]].libC < 2)
goto two; /* a bogus move */
}
else if (gList[gMap[groupIDs[gx][gy]]].libC <= 1)
{
result = TRUE;
goto one;
}
if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim)
{
*escape = TRUE;
result = FALSE;
goto one;
}
if (gList[gMap[groupIDs[gx][gy]]].libC > 1)
{ /* look at my responses */
sSpanGroup(gx, gy, &lList2); /* list his liberties */
dStart = lList2.indx + 1;
if (adjInAtari) /* he wins */
{
result = FALSE;
goto one;
}
if ((lList2.indx > 2) && adj2Libs) /* he wins */
{
result = FALSE;
goto one;
}
for (k = 1; k <= maxSPoint; k++)
libList[k] = -1;
if (utilPlayLevel > 4) /* account for diagonal moves */
{
listDiags(gx, gy, &dList);
j = 0;
k = lList2.indx;
while ((j < dList.indx) &&
(k < maxSPoint))
{
j = j + 1;
k = k + 1;
libList[k] = 100;
lList2.p[k].px = dList.p[j].px;
lList2.p[k].py = dList.p[j].py;
}
lList2.indx = k;
}
if (lList2.indx > 1) /* sort by increasing lib count */
{
for (k = 1; k <= lList2.indx; k++)
if (libList[k] != 100) /* diags go last */
{
mark3 = playMark;
tryPlay(lList2.p[k].px, lList2.p[k].py, me);
libList[k] = gList[gMap[groupIDs[gx][gy]]].libC;
undoTo(mark3);
}
for (k = 1; k <= lList2.indx - 1; k++)
for (j = k + 1; j <= lList2.indx; j++)
if (libList[k] > libList[j])
{
tl = libList[k];
libList[k] = libList[j];
libList[j] = tl;
tp = lList2.p[k];
lList2.p[k] = lList2.p[j];
lList2.p[j] = tp;
}
else if ((libList[k] == libList[j]) &&
(libList[k] == 1))
if (mtNbrs(lList2.p[k].px, lList2.p[k].py) <
mtNbrs(lList2.p[j].px, lList2.p[j].py))
{
tl = libList[k];
libList[k] = libList[j];
libList[j] = tl;
tp = lList2.p[k];
lList2.p[k] = lList2.p[j];
lList2.p[j] = tp;
}
}
for (j = 1; j <= lList2.indx; j++)
{
if (killTree(lList2.p[j].px, lList2.p[j].py, gx,
gy, &esc, tkMark))
goto two; /* this kills him */
if (esc && (j >= dStart))
{
result = FALSE;
goto one; /* don't bother with more diags if escapes */
}
}
result = FALSE; /* none of my responses kills him */
goto one;
}
two:
undoTo(mark2);
}
result = TRUE; /* none of his responses saves him */
}
one:
undoTo(curMark);
/* sClearChar(sChar, rXor); */
depth = depth - 1;
return result;
} /* killTree */
short tKillTree(tx, ty, gx, gy)
short tx, ty, gx, gy;
{ /* tKillTree */
short tkMark, escape;
tryCount = 0;
tkMark = playMark;
return killTree(tx, ty, gx, gy, &escape, tkMark);
} /* tKillTree */
short killable(gx, gy, killx, killy)
short gx, gy, *killx, *killy;
{ /* killable */
#ifdef DEBUG
printf( "killable\n" );
showTrees = TRUE;
#endif
dbStop = TRUE;
him = bord[gx][gy]; /* find out who I am */
me = -him;
/* if (me == 1)
sChar = '>';
else
sChar = '|'; */
/* write(sChar); */
depth = 1;
topMark = playMark;
sSpanGroup(gx, gy, &lList); /* find his liberties */
if (lList.indx == 1)
{
*killx = lList.p[1].px;
*killy = lList.p[1].py;
return TRUE;
}
else if (lList.indx > treeLibLim)
return FALSE;
else if (adjInAtari)
return FALSE;
else if ((lList.indx > 2) && adj2Libs)
return FALSE;
else
{
for (i = 1; i <= maxSPoint; i++)
libList[i] = -1;
if (utilPlayLevel > 4) /* account for diagonal moves */
{
listDiags(gx, gy, &dList);
j = 0;
i = lList.indx;
while ((j < dList.indx) &&
(i < maxSPoint))
{
j = j + 1;
i = i + 1;
libList[i] = 100;
lList.p[i].px = dList.p[j].px;
lList.p[i].py = dList.p[j].py;
}
lList.indx = i;
}
if (lList.indx > 1) /* sort by increasing lib count */
{
for (i = 1; i <= lList.indx; i++)
if (libList[i] != 100) /* diags go last */
{
mark2 = playMark;
tryPlay(lList.p[i].px, lList.p[i].py, me);
libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
undoTo(mark2);
}
for (i = 1; i <= lList.indx - 1; i++)
for (j = i + 1; j <= lList.indx; j++)
if (libList[i] > libList[j])
{
tl = libList[i];
libList[i] = libList[j];
libList[j] = tl;
tp = lList.p[i];
lList.p[i] = lList.p[j];
lList.p[j] = tp;
}
else if ((libList[i] == libList[j]) &&
(libList[i] == 1))
if (mtNbrs(lList.p[i].px, lList.p[i].py) <
mtNbrs(lList.p[j].px, lList.p[j].py))
{
tl = libList[i];
libList[i] = libList[j];
libList[j] = tl;
tp = lList.p[i];
lList.p[i] = lList.p[j];
lList.p[j] = tp;
}
}
for (i = 1; i <= lList.indx; i++)
{
if (legal[lList.p[i].px, lList.p[i].py])
{
*killx = lList.p[i].px;
*killy = lList.p[i].py;
if (tKillTree(*killx, *killy, gx, gy))
{
/* sClearChar(sChar, rXor); */
return TRUE;
}
}
}
return FALSE;
}
/* sClearChar(sChar, rXor); */
} /* killable */